package top.lidee.common.service.twice.third.wechat.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import com.ijpay.core.kit.RsaKit;
import com.wechat.pay.contrib.apache.httpclient.WechatPayUploadHttpPost;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.util.EntityUtils;
import org.springframework.beans.factory.BeanCreationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import top.lidee.common.bean.WxPayV3Bean;
import top.lidee.common.service.twice.applet.MtStoreCateService;
import top.lidee.common.service.twice.management.*;
import top.lidee.common.service.twice.third.wechat.WechatPayJJCommonService;
import top.lidee.framework.enums.CommonExceptionEnum;
import top.lidee.framework.result.ResponseResult;
import top.lidee.repository.model.MtStore;
import top.lidee.repository.model.twice.pojo.applet.MtStoreCateEntity;
import top.lidee.repository.model.twice.pojo.management.MtSecondaryCateSpecialMapEntity;
import top.lidee.repository.model.twice.pojo.management.MtStoreWechatInputPieceLogEntity;
import top.lidee.repository.model.twice.pojo.management.MtUploadCateCertificationLogEntity;
import top.lidee.repository.model.twice.pojo.management.TpbWechatBankAccountEntity;
import top.lidee.utils.MyCollUtil;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.*;
import java.net.URI;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static top.lidee.framework.constant.AlipayDefaultSettleTypeCon.QUALIFYING;
import static top.lidee.framework.constant.GlobalPattern.IMAGE_URL;
import static top.lidee.framework.constant.SupplierInfoConstant.FAIL;
import static top.lidee.framework.constant.SupplierInfoConstant.WAIT;
import static top.lidee.framework.constant.WechatConstant.*;

/**
 * @author 张一恒
 * @version 1.0
 * @description:
 * @date 2024/10/19 09:50
 */
@Service("wechatPayJJCommonService")
@Slf4j
@AllArgsConstructor(onConstructor = @__(@Autowired))
public class WechatPayJJCommonServiceImpl implements WechatPayJJCommonService {

    //微信V3支付Bean
    private final WxPayV3Bean wxPayV3Bean;

    //微信 创建加载商户私钥、加载平台证书、初始化httpClient的通用方法
    private final CloseableHttpClient wxPayNoSignClient;

    //店铺主营行业分类表
    private final MtStoreCateService mtStoreCateService;

    //商户上传店铺二级类目特殊资质记录表
    private final MtUploadCateCertificationLogService mtUploadCateCertificationLogService;

    //二级类目特殊资质集合表
    private final MtSecondaryCateSpecialMapService mtSecondaryCateSpecialMapService;

    //收付通进件记录表
    private final MtStoreWechatInputPieceLogService mtStoreWechatInputPieceLogService;

    private final TpbWechatBankAccountService tpbWechatBankAccountService;


    /**
     * @param managerId
     * @param store
     * @return top.lidee.framework.result.ResponseResult
     * @description 基本校验
     * @author zhangyiheng
     * @date 2024/10/19 09:29
     */
    @Override
    public Map<String, Object> checkInfo(Integer managerId, MtStore store) {
        Map<String, Object> map = new HashMap<>();
        Integer storeId = store.getId();
        if (Objects.isNull(store) || Objects.isNull(store.getCateId())) {
            throw new BeanCreationException(CommonExceptionEnum.DPBCZ.getMsg());
        }

        //查询微信结算银行信息
        TpbWechatBankAccountEntity tpbWechatBankAccount = tpbWechatBankAccountService.getOne(Wrappers.<TpbWechatBankAccountEntity>lambdaQuery().eq(TpbWechatBankAccountEntity::getStoreId, storeId));
        Opt.ofNullable(tpbWechatBankAccount).orElseThrow(() -> new BeanCreationException("无微信结算银行账户信息，无法进件"));


        //校验银行卡信息
        if (Objects.isNull(tpbWechatBankAccount.getBankCardNumber())) {
            throw new BeanCreationException(CommonExceptionEnum.YHKHBNWK.getMsg());
        } else {
            if (StrUtil.isAllBlank(tpbWechatBankAccount.getAccountBranchName(), tpbWechatBankAccount.getAccountInstProvince(), tpbWechatBankAccount.getAccountInstCity(), tpbWechatBankAccount.getBankCardHolder())) {
                throw new BeanCreationException(CommonExceptionEnum.QJCYHKZHM.getMsg());
            }
        }

        //校验超级管理员数据是否存在
        MtStoreWechatInputPieceLogEntity pieceLog = mtStoreWechatInputPieceLogService.getOne(Wrappers.<MtStoreWechatInputPieceLogEntity>lambdaQuery().eq(MtStoreWechatInputPieceLogEntity::getStoreId, storeId).isNull(MtStoreWechatInputPieceLogEntity::getState));
        Opt.ofNullable(pieceLog).ifPresent(this::checkAdminInput).orElseThrow(BeanCreationException::new, "此店铺超级管理员数据不存在，不能微信进件！");

        //获取商户、店铺分类数据，主要获取店铺的二级分类数据
        MtStoreCateEntity cate = mtStoreCateService.getById(store.getCateId());

        if (Objects.isNull(cate) || Objects.isNull(cate.getSecondaryCateCode())) {
            throw new BeanCreationException(CommonExceptionEnum.GDPEJFLBCZ.getMsg());
        }

        if (StrUtil.equalsAny(store.getStatus(), WAIT, FAIL)) {
            throw new BeanCreationException(CommonExceptionEnum.GDPZZXXWX_BNJJ.getMsg());
        }

        //校验是否正在进阶中或已进件状态
        int count = mtStoreWechatInputPieceLogService.count(Wrappers.<MtStoreWechatInputPieceLogEntity>lambdaQuery().eq(MtStoreWechatInputPieceLogEntity::getStoreId, storeId).in(MtStoreWechatInputPieceLogEntity::getState, IN_THE_INCOMING, THE_INCOMING_REVIEW_IS_COMPLETE));

        if (count > 0) {
            throw new BeanCreationException(CommonExceptionEnum.GDPYSJJTGZT.getMsg());
        }

        //校验二级分类是否是特殊的
        if (Objects.equals(cate.getSpecialQualification(), QUALIFYING)) {
            //微信规则是每个主体有可能需要特殊资质有可能不用
            List<String> wechatSubjectTypes = mtSecondaryCateSpecialMapService.list(Wrappers.<MtSecondaryCateSpecialMapEntity>lambdaQuery().eq(MtSecondaryCateSpecialMapEntity::getCateId, store.getCateId())).stream().map(MtSecondaryCateSpecialMapEntity::getWechatSubjectType).collect(Collectors.toList());

            //如果存在最少有一个
            if (wechatSubjectTypes.get(0).contains(store.getPrincipalType())) {
                List<MtUploadCateCertificationLogEntity> mtUploadCateCertificationLogs = mtUploadCateCertificationLogService.list(Wrappers.<MtUploadCateCertificationLogEntity>lambdaQuery().eq(MtUploadCateCertificationLogEntity::getMerchantId, managerId).eq(MtUploadCateCertificationLogEntity::getStoreId, storeId).eq(MtUploadCateCertificationLogEntity::getCateId, cate.getCategoryId()).eq(MtUploadCateCertificationLogEntity::getIsCompliance, 0));

                if (!MyCollUtil.isNotEmpty(mtUploadCateCertificationLogs)) {
                    throw new BeanCreationException(CommonExceptionEnum.RJFLSTSHYXYTSZZTP.getMsg());
                }
                map.put("mtUploadCateCertificationLogs", mtUploadCateCertificationLogs);
            }
        }

        map.put("tpbWechatBankAccount", tpbWechatBankAccount);
        map.put("pieceLog", pieceLog);
        map.put("cate", cate);
        return map;
    }

    /**
     * @param admin
     * @return void
     * @description 微信 特约商户进件超级管理员校验
     * @author zhangyiheng
     * @date 2024/10/22 10:51
     */
    private void checkAdminInput(MtStoreWechatInputPieceLogEntity admin) {
        //超级管理员类型
        Opt.ofBlankAble(admin.getContactType()).orElseThrow(BeanCreationException::new, "请检查超级管理员类型是否选择");
        if (Objects.equals(SUPER, admin.getContactType())) {
            //超级管理员姓名
            Opt.ofBlankAble(admin.getContactName()).orElseThrow(BeanCreationException::new, "请检查经办人姓名是否填写");
            //超级管理员证件类型
            Opt.ofBlankAble(admin.getContactIdDocType()).orElseThrow(BeanCreationException::new, "请检查经办人证件类型是否选择");
            //超级管理员身份证件号码
            Opt.ofBlankAble(admin.getContactIdNumber()).orElseThrow(BeanCreationException::new, "请检查经办人身份证件号码是否填写");
            //超级管理员证件正面照片
            Opt.ofBlankAble(admin.getContactIdDocCopy()).peek(copy -> {
                Pattern r = Pattern.compile(IMAGE_URL);
                if (!r.matcher(copy).find()) {
                    throw new BeanCreationException("请检查经办人证件正面照片是否正确上传");
                }
            }).orElseThrow(BeanCreationException::new, "请检查经办人证件正面照片是否上传");
            //超级管理员证件反面照片
            Opt.ofBlankAble(admin.getContactIdDocCopyBack()).peek(copyB -> {
                Pattern r = Pattern.compile(IMAGE_URL);
                if (!r.matcher(copyB).find()) {
                    throw new BeanCreationException("请检查经办人证件反面照片是否正确上传");
                }
            }).orElseThrow(BeanCreationException::new, "请检查经办人证件反面照片是否上传");
            //业务授权函
            Opt.ofBlankAble(admin.getBusinessAuthorizationLetter()).peek(letter -> {
                Pattern r = Pattern.compile(IMAGE_URL);
                if (!r.matcher(letter).find()) {
                    throw new BeanCreationException("请检查业务授权函照片是否正确上传");
                }
            }).orElseThrow(BeanCreationException::new, "请检查业务授权函照片是否上传");
            //超级管理员证件有效期开始时间
            Opt.ofNullable(admin.getContactPeriodBegin()).orElseThrow(BeanCreationException::new, "请检查经办人证件有效期开始时间是否填写");
            //超级管理员证件有效期结束时间
            Opt.ofNullable(admin.getContactPeriodEnd()).orElseThrow(BeanCreationException::new, "请检查经办人证件有效期结束时间是否填写");
            //超级管理员联系邮箱
            Opt.ofBlankAble(admin.getContactEmail()).orElseThrow(BeanCreationException::new, "请检查经办人联系邮箱是否填写");
            //超级管理员联系手机
            Opt.ofBlankAble(admin.getMobilePhone()).orElseThrow(BeanCreationException::new, "请检查经办人联系手机是否填写");
        } else {
            //超级管理员姓名
            Opt.ofBlankAble(admin.getContactName()).orElseThrow(BeanCreationException::new, "请检查超级管理员姓名是否填写");
            //超级管理员联系邮箱
            Opt.ofBlankAble(admin.getContactEmail()).orElseThrow(BeanCreationException::new, "请检查超级管理员联系邮箱是否填写");
            //超级管理员联系手机
            Opt.ofBlankAble(admin.getMobilePhone()).orElseThrow(BeanCreationException::new, "请检查超级管理员联系手机是否填写");
        }
    }

    /**
     * @param storeId
     * @param to
     * @param httpPost
     * @param store
     * @return top.lidee.framework.result.ResponseResult
     * @description 处理结果
     * @author zhangyiheng
     * @date 2024/10/19 09:43
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public <T> ResponseResult doWXRES(Integer storeId, T to, HttpPost httpPost, MtStore store, String tmp, MtStoreWechatInputPieceLogEntity pieceLog) {
        String reqdata = JSON.toJSONString(to);

        StringEntity entity = new StringEntity(reqdata, "utf-8");
        entity.setContentType("application/json");
        httpPost.setEntity(entity);
        httpPost.setHeader("Accept", "application/json");
        //涉及加密数据需要再请求头带上证书序列号
        httpPost.setHeader("Wechatpay-Serial", wxPayV3Bean.getWechatpayNo());

        pieceLog.setState(IN_THE_INCOMING);
        pieceLog.setStoreId(storeId);

        //完成签名并执行请求
        try (CloseableHttpResponse response = wxPayNoSignClient.execute(httpPost)) {
            /*
            {
              "applyment_id": 2000002124775691,
            }
             */
            int statusCode = response.getStatusLine().getStatusCode();
            if (statusCode == 200) { //处理成功
                String res = EntityUtils.toString(response.getEntity());
                Map map = JSON.parseObject(res, Map.class);
                //微信支付分配的申请单号 。
                Integer applymentId = (Integer) map.get("applyment_id");
                //服务商自定义的商户唯一编号。每个编号对应一个申请单，每个申请单审核通过后会生成一个微信支付商户号。
                String outRequestNo = StrUtil.isBlank(map.get("out_request_no") + "") ? store.getExternalId() : (String) map.get("out_request_no");
                //保存
                pieceLog.setApplymentId(Long.valueOf(applymentId));
                pieceLog.setOutRequestNo(outRequestNo);


                log.info("微信{}，店铺id：{} 处理结果：success,return body = {}", tmp, storeId, EntityUtils.toString(response.getEntity()));
            } else if (statusCode == 204) { //处理成功，无返回Body

                pieceLog.setOutRequestNo(store.getExternalId());

                log.info("微信{}，店铺id：{} 处理结果：success，无微信返回值", tmp, storeId);
            } else {

                pieceLog.setOutRequestNo(store.getExternalId());
                pieceLog.setState(INCOMING_ITEMS_ARE_ABNORMAL);

                log.error("微信{}，店铺id：{} 处理结果：failed,resp code = {},return body = {}", tmp, storeId, statusCode, EntityUtils.toString(response.getEntity()));
            }
            pieceLog.setStatusCode(statusCode);
            mtStoreWechatInputPieceLogService.saveOrUpdate(pieceLog);
        } catch (Exception e) {
            log.error("微信{}，店铺id：{} 异常：{}", tmp, storeId, e.getMessage(), e);
        }
        return ResponseResult.ok();
    }


    /**
     * @param message
     * @return java.lang.String
     * @description 信息加密
     * 参考：https://pay.weixin.qq.com/docs/partner/development/interface-rules/sensitive-data-encryption.html
     * @author zhangyiheng
     * @date 2024/10/5 11:50
     */
    @Override
    public String rsaEncryptOAEP(String message, X509Certificate certificate) {
        try {
            Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-1AndMGF1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, certificate.getPublicKey());

            byte[] data = message.getBytes(StandardCharsets.UTF_8);
            byte[] cipherdata = cipher.doFinal(data);
            return Base64.getEncoder().encodeToString(cipherdata);
        } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
            log.error("当前Java环境不支持RSA v1.5/OAEP", e);
            throw new BeanCreationException("系统异常，请联系管理员");
        } catch (InvalidKeyException e) {
            log.error("无效的证书", e);
            throw new BeanCreationException("系统异常，请联系管理员");
        } catch (IllegalBlockSizeException | BadPaddingException e) {
            log.error("加密原串的长度不能超过214字节", e);
            throw new BeanCreationException("系统异常，请联系管理员");
        }
    }


    /**
     * 获取证书。
     * 参考：https://pay.weixin.qq.com/wiki/doc/apiv3/wechatpay/wechatpay7_0.shtml
     *
     * @param filePath 证书文件路径  (required)
     * @return X509证书
     */
    @Override
    public X509Certificate getCertificate(String filePath) {
        try {
            InputStream fis = Files.newInputStream(Paths.get(filePath));

            try (BufferedInputStream bis = new BufferedInputStream(fis)) {
                CertificateFactory cf = CertificateFactory.getInstance("X509");
                X509Certificate cert = (X509Certificate) cf.generateCertificate(bis);
                cert.checkValidity();
                return cert;
            } catch (CertificateExpiredException e) {
                log.error("证书已过期", e);
                throw new BeanCreationException("系统异常，请联系管理员");
            } catch (CertificateNotYetValidException e) {
                log.error("证书尚未生效", e);
                throw new BeanCreationException("系统异常，请联系管理员");
            } catch (CertificateException e) {
                log.error("无效的证书文件", e);
                throw new BeanCreationException("系统异常，请联系管理员");
            }
        } catch (IOException e) {
            log.error("微信证书获取失败", e);
            throw new BeanCreationException("系统异常，请联系管理员");
        }
    }

    /**
     * 获取商户私钥
     *
     * @param keyPath 商户私钥证书路径
     * @return 商户私钥
     * @throws Exception 解析 key 异常
     */
    public String getPrivateKey(String keyPath) throws Exception {
        String originalKey = FileUtil.readUtf8String(keyPath);
        String privateKey = originalKey
                .replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s+", "");
        return RsaKit.getPrivateKeyStr(RsaKit.loadPrivateKey(privateKey));
    }


    /**
     * @return String
     * @description 图片上传API
     * 部分微信支付业务指定商户需要使用图片上传 API来上报图片信息，从而获得必传参数的值：图片MediaID 。
     * @author zhangyiheng
     * @date 2024/10/5 07:09
     */
    @Override
    public String wxGetImageMediaId(String imageUrl) {
        //媒体图片只支持JPG、BMP、PNG格式，文件大小不能超过2M。

        //网络图片转file
        File file = urlToFile(imageUrl);
        //判断文件大小
        if (file.isFile()) {
            if (file.length() > 2000000) {
                log.error("不符合微信图片上传API要求，文件大小不能超过2m");
                throw new BeanCreationException("系统错误，请联系管理员");
            }
        }
        try {
            URI uri = new URI(wxPayV3Bean.getImageMediaIdUrl());

            try (FileInputStream ins1 = new FileInputStream(file)) {
                String sha256 = DigestUtils.sha256Hex(ins1);
                try (InputStream ins2 = Files.newInputStream(file.toPath())) {
                    HttpPost request = new WechatPayUploadHttpPost.Builder(uri).withImage(file.getName(), sha256, ins2).build();

                    CloseableHttpResponse response1 = wxPayNoSignClient.execute(request);
                    HttpEntity entity = response1.getEntity();
                    String mediaId = EntityUtils.toString(entity);
                    mediaId = JSON.parseObject(mediaId).getString("media_id");
                    if (entity.getContent() != null) {
                        entity.getContent().close();
                    }
                    if (StrUtil.isBlank(mediaId)) {
                        log.error("图片上传API错误");
                        throw new BeanCreationException("系统错误请重试");
                    }
                    return mediaId;
                }
            }
        } catch (Exception e) {
            log.error("图片上传API接口调用失败：{}", e.getMessage(), e);
            throw new BeanCreationException(e.getMessage());
        } finally {
            //删除文件
            Path path = Paths.get(file.getPath());
            try (Stream<Path> walk = Files.walk(path)) {
                walk.sorted(Comparator.reverseOrder()).forEach(WechatPayJJCommonServiceImpl::deleteDirectoryStream);
            } catch (IOException e) {
                log.error("文件删除失败：{}", file.getPath() + file.getName(), e);
            }
        }
    }

    private static void deleteDirectoryStream(Path path) {
        try {
            Files.delete(path);
        } catch (IOException e) {
            log.error("无法删除的路径:{},错误信息：{}", path, e.getMessage(), e);
        }
    }

    /**
     * @param fileUrl 资源地址
     * @return java.io.File
     * @description: 网络资源转file, 用完以后必须删除该临时文件
     * @author zhangyiheng
     * @date 2024/10/5 08:11
     */
    public File urlToFile(String fileUrl) {
        String path = System.getProperty("user.dir");
        File tmpFile = new File(path, "tmp");
        if (!tmpFile.exists()) {
            tmpFile.mkdirs();
        }

        String fileName = fileUrl.substring(fileUrl.lastIndexOf("/"));
        //判断后缀
        String fileType = FilenameUtils.getExtension(fileName).toLowerCase();
        if (!StrUtil.equalsAnyIgnoreCase(fileType, "jpg", "bmp", "png")) {
            fileName = fileName.substring(0, fileName.lastIndexOf("."));
            fileName = fileName + ".png";
        }
        FileOutputStream downloadFile = null;
        InputStream openStream = null;
        File savedFile = null;
        try {
            savedFile = new File(tmpFile.getAbsolutePath() + fileName);
            URL url = new URL(fileUrl);
            java.net.HttpURLConnection connection = (java.net.HttpURLConnection) url.openConnection();
            openStream = connection.getInputStream();
            int index;
            byte[] bytes = new byte[1024];
            downloadFile = new FileOutputStream(savedFile);
            while ((index = openStream.read(bytes)) != -1) {
                downloadFile.write(bytes, 0, index);
                downloadFile.flush();
            }
        } catch (Exception e) {
            log.error("网络资源转file异常:{}", e.getMessage(), e);
        } finally {
            try {
                if (openStream != null) {
                    openStream.close();
                }
                if (downloadFile != null) {
                    downloadFile.close();
                }
            } catch (Exception e) {
                log.error("网络资源转file释放资源异常:{}", e.getMessage(), e);
            }
        }
        return savedFile;
    }


    /**
     * @param url
     * @param tmp
     * @return org.apache.http.client.methods.CloseableHttpResponse
     * @description 发送请求get
     * @author zhangyiheng
     * @date 2024/10/8 16:56
     */
    @Override
    public Map<String, Object> pushRequestOfGetApply(String url, String tmp) {
        //请求URL
        HttpGet httpGet = new HttpGet(url);
        HashMap<String, Object> map = Maps.newHashMap();
        //请求
        try (CloseableHttpResponse response = wxPayNoSignClient.execute(httpGet)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (Objects.equals(200, statusCode)) { //处理成功
                String res = EntityUtils.toString(response.getEntity());
                map.put("res", res);
                log.info("{}查询申请状态API成功，处理结果：success,return body = {}", tmp, EntityUtils.toString(response.getEntity()));
            } else if (Objects.equals(204, statusCode)) { //处理成功，无返回Body
                log.info("{}查询申请状态API成功  处理结果：success，无微信返回值:{}", tmp, Optional.ofNullable(EntityUtils.toString(response.getEntity())).orElse(""));
            } else {
                log.error("{}查询申请状态API失败 处理结果：failed,resp code = {},return body = {}", tmp, statusCode, EntityUtils.toString(response.getEntity()));
                throw new BeanCreationException(EntityUtils.toString(response.getEntity()));
            }
            map.put("code", statusCode);
        } catch (Exception e) {
            log.error("{}查询申请状态API异常：{}", tmp, e.getMessage(), e);
            throw new BeanCreationException(e.getMessage());
        }
        return map;
    }


    /**
     * @param url
     * @return org.apache.http.client.methods.CloseableHttpResponse
     * @description 发送请求get
     * @author zhangyiheng
     * @date 2024/10/8 16:56
     */
    private Map commonPushRequestOfGet(String url) {
        //请求URL
        HttpGet httpGet = new HttpGet(url);
        httpGet.setHeader("Accept", "application/json");
        //请求
        try (CloseableHttpResponse response = wxPayNoSignClient.execute(httpGet)) {
            int statusCode = response.getStatusLine().getStatusCode();
            if (Objects.equals(200, statusCode)) { //处理成功
                String res = EntityUtils.toString(response.getEntity());
                Map map = JSON.parseObject(res, Map.class);
                log.info("success,return body = {}", EntityUtils.toString(response.getEntity()));
                return map;
            } else if (Objects.equals(204, statusCode)) { //处理成功，无返回Body
                log.info("success，无微信返回值:{}", Optional.ofNullable(EntityUtils.toString(response.getEntity())).orElse(""));
            } else {
                log.error("failed,resp code = {},return body = {}", statusCode, EntityUtils.toString(response.getEntity()));
                throw new BeanCreationException(EntityUtils.toString(response.getEntity()));
            }
        } catch (Exception e) {
            throw new BeanCreationException(e.getMessage());
        }
        throw new BeanCreationException("commonPushRequestOfGet failed");
    }

    /**
     * @return java.lang.String
     * @description 获取微信证书序列号
     * 【证书序列号】 平台证书的主键，唯一定义此资源的标识
     * @author zhangyiheng
     * @date 2024/10/24 12:30
     */
    @Override
    public String getSerialNo() {
        return certificates("serial_no");
    }


    /**
     * @return java.lang.String
     * @description 下载平台证书
     * 获取商户当前可用的平台证书列表。微信支付提供该接口，帮助商户后台系统实现平台证书的平滑更换。该请求无需身份认证信息之外的其他参数。
     * https://pay.weixin.qq.com/docs/partner/apis/platform-certificate/api-v3-get-certificates/get.html
     * @author zhangyiheng
     * @date 2024/10/24 12:32
     */
    private String certificates(String filed) {
        Map map = commonPushRequestOfGet(wxPayV3Bean.getCertificatesUrl());
        Object data = map.get("data");
        List parsed = JSON.parseObject(data.toString(), List.class);
        for (Object obj : parsed) {
            Map m = JSON.parseObject(obj.toString(), Map.class);
            return (String) m.get(filed);
        }
        return null;
    }

}
